﻿using System;
using System.IO;
using System.Linq;
using AutoMapper;
using JTTD.DataBase;
using JTTD.Domain;
using JTTD.Domain.IWebApi;
using JTTD.Error;
using JTTD.Extensions;
using log4net;
using log4net.Config;
using log4net.Repository;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.ResponseCompression;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.PlatformAbstractions;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Swashbuckle.AspNetCore.Swagger;
using WebApiClient;
using IdentityModel;
using JTTD.Model;
using IdentityServer4.AspNetIdentity;
using Autofac.Extensions.DependencyInjection;
using System.Reflection;
using Autofac;
using System.Collections.Generic;
using JTTD.Domain.IService;
using JTTD.Controllers;
using JTTD.Domain.Service;

namespace JTTD
{
    /// <summary>
    /// 
    /// </summary>
    public class Startup
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="configuration"></param>
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
            Repository = LogManager.CreateRepository("NETCoreRepository");
            XmlConfigurator.Configure(Repository, new FileInfo("log4net.config"));
            InitRepository.LoggerRepository = Repository;
        }
        /// <summary>
        /// 
        /// </summary>
        public IConfiguration Configuration { get; }
        /// <summary>
        /// 
        /// </summary>
        public static ILoggerRepository Repository { get; set; }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="services"></param>
        // This method gets called by the runtime. Use this method to add services to the container.
        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            var url = Configuration.GetValue<string>("ASPNETCORE_URLS");
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2).AddJsonOptions(options =>
            {
                //忽略循环引用
                options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
                //不使用驼峰样式的key
                options.SerializerSettings.ContractResolver = new DefaultContractResolver();
                //设置时间格式
                options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";

                //options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
            });
            services.AddMvc(o =>{}).SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
                    .ConfigureApiBehaviorOptions(o =>{ o.SuppressModelStateInvalidFilter = true;});
            services.AddSession();
            services.AddSingleton<IWeiXinService, WeiXinService>();
            services.AddDbContext<JTTDContext>(d => d.UseMySql(Configuration.GetConnectionString("Default")));
            services.AddAutoMapper(typeof(AutoMapperConfigs));
            services.AddAuthentication("Bearer")
                    .AddIdentityServerAuthentication(options =>
                    {
                        options.Authority = url;//identifyServer服务地址
                        options.RequireHttpsMetadata = false;//是否使用https
                        options.ApiName = "jttdApi";//进行身份验证的API资源的名称
                    });
            services.AddIdentityServer()
                .AddDeveloperSigningCredential()
                .AddInMemoryIdentityResources(TokenConfig.GetIdentityResources())//用户信息建模
                .AddInMemoryApiResources(TokenConfig.GetApiResources())//添加api资源
                .AddInMemoryClients(TokenConfig.GetClients())//添加客户端
                .AddResourceOwnerValidator<LoginValidator>()//用户校验
                .AddProfileService<ProfileService>();
            services.AddSwaggerGen(options =>
            {
                options.SwaggerDoc("ChannelApi", new Info
                {
                    Version = "1.0",
                    Title = "JTTD Api",
                    Description = "上海井亭生活项目业务功能Api",
                    //TermsOfService = "None",
                    Contact = new Contact { Name = "JTTD", Email = "", Url = url }
                });
                options.SchemaFilter<Extensions.Swagger.SwaggerExcludeFilter>();
                options.OperationFilter<Extensions.Swagger.SwaggerFileUploadFilter>();
                var basePath = PlatformServices.Default.Application.ApplicationBasePath;
                var xmlPathApi = Path.Combine(basePath, "JTTD.xml");
                var xmlPathModel = Path.Combine(basePath, "JTTDDTO.xml");
                options.IncludeXmlComments(xmlPathApi);
                options.IncludeXmlComments(xmlPathModel);

                options.AddSecurityDefinition("Bearer", new ApiKeyScheme
                {
                    Description = "JWT Bearer 授权 \"Authorization:     Bearer+空格+token\"",
                    Name = "Authorization",
                    In = "header",
                    Type = "apiKey"
                });

                //options.AddSecurityDefinition("oauth2", new OAuth2Scheme
                //{
                //    Flow = "implicit",
                //    AuthorizationUrl = url + "/connect/authorize",
                //    Scopes = new Dictionary<string, string> {
                //        { "jttdApi", "上海井亭生活项目业务功能Api" }
                //    }
                //});

                options.OperationFilter<AuthResponsesOperationFilter>();
            });
            services.AddMvc(options =>
            {
                options.Filters.Add(typeof(HttpGlobalExceptionFilter)); //加入全局异常类
            });
            HttpApi.Register<IDomainApi>().ConfigureHttpApiConfig(c =>
            {
                c.HttpHost = new Uri(url);
                c.FormatOptions.DateTimeFormat = DateTimeFormats.ISO8601_WithMillisecond;
            });
            // Brotli和Gzip压缩
            services.AddResponseCompression(options =>
            {
                options.Providers.Add<BrotliCompressionProvider>();
                options.Providers.Add<GzipCompressionProvider>();
                options.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(new[] { "image/svg+xml" });
            });
            //启用跨域
            services.AddCors(options =>
            {
                options.AddPolicy("any", builder =>
                {
                    builder.AllowAnyOrigin() //允许任何来源的主机访问
                    .AllowAnyMethod()
                    .AllowAnyHeader()
                    .AllowCredentials();//指定处理cookie

                });
            });
            var containerbuilder = new ContainerBuilder();//实例化 AutoFac  容器   

            var assemblys = Assembly.Load("JTTD.Domain");//Service是继承接口的实现方法类库名称
            var baseType = typeof(IDependency);//IDependency 是一个接口（所有要实现依赖注入的借口都要继承该接口）
            containerbuilder.RegisterAssemblyTypes(assemblys)
              .Where(m => baseType.IsAssignableFrom(m) && m != baseType)
              .AsImplementedInterfaces()
              .InstancePerLifetimeScope();
            containerbuilder.Populate(services);
            var ApplicationContainer = containerbuilder.Build();
            return new AutofacServiceProvider(ApplicationContainer);//第三方IOC接管 core内置DI容器
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="app"></param>
        /// <param name="env"></param>
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            var log = LogManager.GetLogger(Repository.Name, typeof(Startup));
            log.Info("test");
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseStaticFiles();
            app.UseSwagger();
            app.UseCors(builder =>
            {
                builder.WithOrigins("http://*").AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin().AllowCredentials();
            });
            //使用IdentityServer
            app.UseIdentityServer();
            app.UseSession();
            //使用认证
            app.UseAuthentication();
            app.UseSwaggerUI(c =>
            {
                c.SwaggerEndpoint("/swagger/ChannelApi/swagger.json", "JTTD");
                c.RoutePrefix = "swagger";
            });
            app.UseMvc();
        }
    }
}
